* New properties: links, templates, images, langlinks, categories, external links
* Breaking Change: imagelinks renamed into imageusage (il->iu)
* Bug fix: incorrect generator behavior in some cases
+* JSON format allows an optional callback function to wrap the result.
* Login module disabled until a more secure solution can be implemented
* (bug 9938) Querying by revision identifier returns the most recent revision
for the corresponding page, rather than the requested revision
* (bug 8772) Filter page revision queries by user
* (bug 9927) User contributions queries do not accept IP addresses
-* Watchlist now reports a proper feed item when the user is not logged in
-* Watchlist date bug fixed - automatically shows one last day
+* Watchlist Feed now reports a proper feed item when the user is not logged in
+* Watchlist Feed date bug fixed - automatically shows one last day
+* Watchlist Feed now allows to specify number of hours to monitor
== Maintenance script changes since 1.10 ==
const PARAM_DFLT = 0;
const PARAM_ISMULTI = 1;
const PARAM_TYPE = 2;
- const PARAM_MAX1 = 3;
+ const PARAM_MAX = 3;
const PARAM_MAX2 = 4;
const PARAM_MIN = 5;
if (is_array($type)) {
$desc .= $paramPrefix . $prompt . implode(', ', $type);
- }
- elseif ($type == 'namespace') {
- // Special handling because namespaces are type-limited, yet they are not given
- $desc .= $paramPrefix . $prompt . implode(', ', ApiBase :: getValidNamespaces());
+ } else {
+ switch ($type) {
+ case 'namespace':
+ // Special handling because namespaces are type-limited, yet they are not given
+ $desc .= $paramPrefix . $prompt . implode(', ', ApiBase :: getValidNamespaces());
+ break;
+ case 'limit':
+ $desc .= $paramPrefix . "No more than {$paramSettings[self :: PARAM_MAX]} ({$paramSettings[self :: PARAM_MAX2]} for bots) allowed.";
+ break;
+ case 'integer':
+ $hasMin = isset($paramSettings[self :: PARAM_MIN]);
+ $hasMax = isset($paramSettings[self :: PARAM_MAX]);
+ if ($hasMin || $hasMax) {
+ if (!$hasMax)
+ $intRangeStr = "The value must be no less than {$paramSettings[self :: PARAM_MIN]}";
+ elseif (!$hasMin)
+ $intRangeStr = "The value must be no more than {$paramSettings[self :: PARAM_MAX]}";
+ else
+ $intRangeStr = "The value must be between {$paramSettings[self :: PARAM_MIN]} and {$paramSettings[self :: PARAM_MAX]}";
+
+ $desc .= $paramPrefix . $intRangeStr;
+ }
+ break;
+ }
}
}
+
$default = is_array($paramSettings) ? (isset ($paramSettings[self :: PARAM_DFLT]) ? $paramSettings[self :: PARAM_DFLT] : null) : $paramSettings;
if (!is_null($default) && $default !== false)
break;
case 'string' : // nothing to do
break;
- case 'integer' : // Force everything using intval()
+ case 'integer' : // Force everything using intval() and optionally validate limits
+
$value = is_array($value) ? array_map('intval', $value) : intval($value);
+ $checkMin = isset ($paramSettings[self :: PARAM_MIN]);
+ $checkMax = isset ($paramSettings[self :: PARAM_MAX]);
+
+ if ($checkMin || $checkMax) {
+ $min = $checkMin ? $paramSettings[self :: PARAM_MIN] : false;
+ $max = $checkMax ? $paramSettings[self :: PARAM_MAX] : false;
+
+ $values = is_array($value) ? $value : array($value);
+ foreach ($values as $v) {
+ if ($checkMin && $v < $checkMin)
+ $this->dieUsage("$paramName may not be less than $min (set to $v)", $paramName);
+ if ($checkMax && $v > $checkMax)
+ $this->dieUsage("$paramName may not be over $max (set to $v)", $paramName);
+ }
+ }
break;
case 'limit' :
- if (!isset ($paramSettings[self :: PARAM_MAX1]) || !isset ($paramSettings[self :: PARAM_MAX2]))
+ if (!isset ($paramSettings[self :: PARAM_MAX]) || !isset ($paramSettings[self :: PARAM_MAX2]))
ApiBase :: dieDebug(__METHOD__, "MAX1 or MAX2 are not defined for the limit $paramName");
if ($multi)
ApiBase :: dieDebug(__METHOD__, "Multi-values not supported for $paramName");
$min = isset ($paramSettings[self :: PARAM_MIN]) ? $paramSettings[self :: PARAM_MIN] : 0;
$value = intval($value);
- $this->validateLimit($paramName, $value, $min, $paramSettings[self :: PARAM_MAX1], $paramSettings[self :: PARAM_MAX2]);
+ $this->validateLimit($paramName, $value, $min, $paramSettings[self :: PARAM_MAX], $paramSettings[self :: PARAM_MAX2]);
break;
case 'boolean' :
if ($multi)
}
public function execute() {
- $feedformat = null;
- extract($this->extractRequestParams());
-
- // limit to 1 day going from now back
- $endTime = wfTimestamp(TS_MW, time() - intval(1 * 24 * 60 * 60));
+ $params = $this->extractRequestParams();
+
+ // limit to the number of hours going from now back
+ $endTime = wfTimestamp(TS_MW, time() - intval($params['hours'] * 60 * 60));
// Prepare nested request
- $params = new FauxRequest(array (
+ $fauxReq = new FauxRequest(array (
'action' => 'query',
'meta' => 'siteinfo',
'siprop' => 'general',
'list' => 'watchlist',
'wlprop' => 'user|comment|timestamp',
- 'wldir' => 'older',
- 'wlend' => $endTime,
+ 'wldir' => 'older', // reverse order - from newest to oldest
+ 'wlend' => $endTime, // stop at this time
'wllimit' => 50
));
// Execute
- $module = new ApiMain($params);
+ $module = new ApiMain($fauxReq);
+
+ global $wgFeedClasses, $wgSitename, $wgContLanguageCode;
try {
$module->execute();
$feedItems[] = $this->createFeedItem($info);
}
- global $wgFeedClasses, $wgSitename, $wgContLanguageCode;
$feedTitle = $wgSitename . ' - ' . wfMsgForContent('watchlist') . ' [' . $wgContLanguageCode . ']';
$feedUrl = SpecialPage::getTitleFor( 'Watchlist' )->getFullUrl();
- $feed = new $wgFeedClasses[$feedformat] ($feedTitle, htmlspecialchars(wfMsgForContent('watchlist')), $feedUrl);
+ $feed = new $wgFeedClasses[$params['feedformat']] ($feedTitle, htmlspecialchars(wfMsgForContent('watchlist')), $feedUrl);
ApiFormatFeedWrapper :: setResult($this->getResult(), $feed, $feedItems);
// Error results should not be cached
$this->getMain()->setCacheMaxAge(0);
- global $wgFeedClasses, $wgSitename, $wgContLanguageCode;
$feedTitle = $wgSitename . ' - Error - ' . wfMsgForContent('watchlist') . ' [' . $wgContLanguageCode . ']';
$feedUrl = SpecialPage::getTitleFor( 'Watchlist' )->getFullUrl();
- $feed = new $wgFeedClasses[$feedformat] ($feedTitle, htmlspecialchars(wfMsgForContent('watchlist')), $feedUrl);
+ $feed = new $wgFeedClasses[$params['feedformat']] ($feedTitle, htmlspecialchars(wfMsgForContent('watchlist')), $feedUrl);
if ($e instanceof UsageException) {
'feedformat' => array (
ApiBase :: PARAM_DFLT => 'rss',
ApiBase :: PARAM_TYPE => $feedFormatNames
+ ),
+ 'hours' => array (
+ ApiBase :: PARAM_DFLT => 24,
+ ApiBase :: PARAM_TYPE => 'integer',
+ ApiBase :: PARAM_MIN => 1,
+ ApiBase :: PARAM_MAX => 72,
)
);
}
protected function getParamDescription() {
return array (
- 'feedformat' => 'The format of the feed'
+ 'feedformat' => 'The format of the feed',
+ 'hours' => 'List pages modified within this many hours from now'
);
}
ApiBase :: PARAM_DFLT => 10,
ApiBase :: PARAM_TYPE => 'limit',
ApiBase :: PARAM_MIN => 1,
- ApiBase :: PARAM_MAX1 => ApiBase :: LIMIT_BIG1,
+ ApiBase :: PARAM_MAX => ApiBase :: LIMIT_BIG1,
ApiBase :: PARAM_MAX2 => ApiBase :: LIMIT_BIG2
)
);
ApiBase :: PARAM_DFLT => 10,
ApiBase :: PARAM_TYPE => 'limit',
ApiBase :: PARAM_MIN => 1,
- ApiBase :: PARAM_MAX1 => ApiBase :: LIMIT_BIG1,
+ ApiBase :: PARAM_MAX => ApiBase :: LIMIT_BIG1,
ApiBase :: PARAM_MAX2 => ApiBase :: LIMIT_BIG2
)
);
ApiBase :: PARAM_DFLT => 10,
ApiBase :: PARAM_TYPE => 'limit',
ApiBase :: PARAM_MIN => 1,
- ApiBase :: PARAM_MAX1 => ApiBase :: LIMIT_BIG1,
+ ApiBase :: PARAM_MAX => ApiBase :: LIMIT_BIG1,
ApiBase :: PARAM_MAX2 => ApiBase :: LIMIT_BIG2
)
);
ApiBase :: PARAM_DFLT => 10,
ApiBase :: PARAM_TYPE => 'limit',
ApiBase :: PARAM_MIN => 1,
- ApiBase :: PARAM_MAX1 => ApiBase :: LIMIT_BIG1,
+ ApiBase :: PARAM_MAX => ApiBase :: LIMIT_BIG1,
ApiBase :: PARAM_MAX2 => ApiBase :: LIMIT_BIG2
)
);
'limit' => array (
ApiBase :: PARAM_TYPE => 'limit',
ApiBase :: PARAM_MIN => 1,
- ApiBase :: PARAM_MAX1 => ApiBase :: LIMIT_SML1,
+ ApiBase :: PARAM_MAX => ApiBase :: LIMIT_SML1,
ApiBase :: PARAM_MAX2 => ApiBase :: LIMIT_SML2
),
'startid' => array (
ApiBase :: PARAM_DFLT => 10,
ApiBase :: PARAM_TYPE => 'limit',
ApiBase :: PARAM_MIN => 1,
- ApiBase :: PARAM_MAX1 => ApiBase :: LIMIT_BIG1,
+ ApiBase :: PARAM_MAX => ApiBase :: LIMIT_BIG1,
ApiBase :: PARAM_MAX2 => ApiBase :: LIMIT_BIG2
),
'start' => array (
ApiBase :: PARAM_DFLT => 10,
ApiBase :: PARAM_TYPE => 'limit',
ApiBase :: PARAM_MIN => 1,
- ApiBase :: PARAM_MAX1 => ApiBase :: LIMIT_BIG1,
+ ApiBase :: PARAM_MAX => ApiBase :: LIMIT_BIG1,
ApiBase :: PARAM_MAX2 => ApiBase :: LIMIT_BIG2
),
'prop' => array (